"""
测试执行脚本，用于运行测试用例并生成Allure报告和轨迹
"""
import os
import sys
import shutil
import argparse
import subprocess
from datetime import datetime

# 定义目录
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TESTS_DIR = os.path.join(BASE_DIR, "tests")
RESULTS_DIR = os.path.join(BASE_DIR, "allure-results")
REPORT_DIR = os.path.join(BASE_DIR, "allure-report")
TRACE_DIR = os.path.join(BASE_DIR, "playwright-traces")

def parse_args():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(description="运行测试用例并生成报告")
    parser.add_argument("--tests", "-t", default="all", help="要运行的测试文件或目录，例如: login_test.py")
    parser.add_argument("--browser", "-b", default="chromium", choices=["chromium", "firefox", "webkit"], 
                        help="使用的浏览器")
    parser.add_argument("--headless", action="store_true", help="是否使用无头模式")
    parser.add_argument("--workers", "-w", type=int, default=1, help="并行工作进程数")
    parser.add_argument("--no-trace", action="store_true", help="禁用轨迹记录")
    parser.add_argument("--no-video", action="store_true", help="禁用视频记录")
    parser.add_argument("--skip-browser-check", action="store_true", help="跳过浏览器检查")
    return parser.parse_args()

def setup_directories():
    """设置必要的目录"""
    # 清理旧的结果
    if os.path.exists(RESULTS_DIR):
        shutil.rmtree(RESULTS_DIR)
    os.makedirs(RESULTS_DIR, exist_ok=True)
    
    # 创建轨迹目录
    os.makedirs(TRACE_DIR, exist_ok=True)
    
    # 创建截图目录
    os.makedirs(os.path.join(BASE_DIR, "screenshots"), exist_ok=True)

def check_browser_installation(browser_name):
    """检查浏览器是否已安装"""
    try:
        # 使用playwright安装状态命令检查浏览器是否已安装
        result = subprocess.run(
            ["playwright", "install", "--dry-run"], 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE,
            text=True,
            check=False
        )
        
        # 检查输出中是否包含浏览器已安装的信息
        if f"{browser_name} is already installed" not in result.stdout:
            print(f"警告: {browser_name} 浏览器可能未安装，尝试安装...")
            subprocess.run(["playwright", "install", browser_name], check=True)
            print(f"{browser_name} 浏览器安装完成")
        else:
            print(f"{browser_name} 浏览器已安装")
            
    except (subprocess.SubprocessError, FileNotFoundError) as e:
        print(f"警告: 无法检查或安装浏览器: {str(e)}")
        print("请手动运行 'playwright install' 来安装所需浏览器")

def run_tests(args):
    """运行测试用例"""
    print(f"开始运行测试... ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})")
    
    # 检查浏览器安装
    if not args.skip_browser_check:
        check_browser_installation(args.browser)
    
    # 构建pytest参数
    pytest_args = [
        "-v",
        "--alluredir", RESULTS_DIR,
    ]
    
    # 添加浏览器参数
    pytest_args.extend(["--browser", args.browser])
    
    # 添加并行运行参数
    if args.workers > 1:
        pytest_args.extend(["-n", str(args.workers)])
    
    # 添加轨迹参数
    if not args.no_trace:
        trace_option = "on" if not args.headless else "retain-on-failure"
        pytest_args.extend(["--tracing", trace_option])
    
    # 添加视频参数
    if not args.no_video:
        pytest_args.extend(["--video", "retain-on-failure"])
    
    # 添加无头模式参数
    if args.headless:
        pytest_args.append("--headed")
    
    # 添加指定的测试
    if args.tests != "all":
        if os.path.isfile(os.path.join(TESTS_DIR, args.tests)):
            test_path = os.path.join(TESTS_DIR, args.tests)
        else:
            print(f"错误: 找不到测试文件 {args.tests}")
            return 1
    else:
        test_path = TESTS_DIR
    
    # 构建完整命令
    cmd = [sys.executable, "-m", "pytest", test_path] + pytest_args
    
    # 执行测试
    print(f"执行命令: {' '.join(cmd)}")
    result = subprocess.run(cmd)
    return result.returncode

def generate_report():
    """生成Allure报告"""
    print("生成Allure报告...")
    
    # 检查是否已安装allure命令
    try:
        subprocess.run(["allure", "--version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except (subprocess.SubprocessError, FileNotFoundError):
        print("警告: Allure命令行工具未安装，将跳过报告生成。")
        print("请访问 https://docs.qameta.io/allure/ 了解如何安装Allure命令行工具。")
        return False
    
    # 生成报告
    if os.path.exists(REPORT_DIR):
        shutil.rmtree(REPORT_DIR)
    
    subprocess.run(["allure", "generate", RESULTS_DIR, "-o", REPORT_DIR, "--clean"])
    print(f"报告已生成在: {REPORT_DIR}")
    
    return True

def open_report():
    """打开Allure报告"""
    try:
        subprocess.run(["allure", "open", REPORT_DIR])
    except subprocess.SubprocessError:
        print(f"请手动打开报告: {REPORT_DIR}")

def main():
    """主函数"""
    args = parse_args()
    setup_directories()
    
    try:
        exit_code = run_tests(args)
        
        if exit_code == 0:
            print("所有测试通过!")
        else:
            print(f"测试失败，退出代码: {exit_code}")
        
        report_generated = generate_report()
        if report_generated and exit_code == 0:
            open_report()
            
        return exit_code
    except KeyboardInterrupt:
        print("\n测试被用户中断")
        return 130
    except Exception as e:
        print(f"运行测试时发生错误: {str(e)}")
        import traceback
        traceback.print_exc()
        return 1

if __name__ == "__main__":
    sys.exit(main()) 